Skip to content

fix: expose plugin root to claude -p via --add-dir#1

Merged
nicknikolakakis merged 1 commit into
mainfrom
fix/add-dir-plugin-root
May 28, 2026
Merged

fix: expose plugin root to claude -p via --add-dir#1
nicknikolakakis merged 1 commit into
mainfrom
fix/add-dir-plugin-root

Conversation

@nicknikolakakis

Copy link
Copy Markdown
Collaborator

Summary

The action spawned claude -p with cwd set to a per-case tempfile.mkdtemp(...) working directory and no --add-dir flag, so the subprocess could only read files inside that temp dir.

Skills that reference plugin-shipped reference files via the documented ${CLAUDE_PLUGIN_ROOT} plugin convention (e.g. shared registries under ${CLAUDE_PLUGIN_ROOT}/data/*.yaml, per-feature config under ${CLAUDE_PLUGIN_ROOT}/spaces/*/*.md, shared CSS / templates) had every Read and Grep denied because the resolved path was outside the allowed working directory. The agent could never get past the first step of any non-trivial skill that loads its own reference data.

Change

scripts/eval.py:

  • Resolve PLUGIN_ROOT = SKILL_PATH.resolve().parent.parent at module load (e.g. plugins/<plugin>/skills/<skill> -> plugins/<plugin>).
  • Pass --add-dir <PLUGIN_ROOT> to the claude -p subprocess in _run_claude.

.resolve() is required because --add-dir is interpreted relative to the subprocess cwd (the per-case temp dir); a relative SKILL_PATH (as set by the composite action input when callers pass a workspace-relative path) would otherwise expand to a nonexistent path inside that temp dir.

Two-line change, no API or input surface change.

Why this is safe

--add-dir is additive on top of cwd. It only widens read access to the resolved plugin root; it does not change tool permissions or model behaviour. The per-case temp working directory continues to scope writes and the primary file surface for the eval case.

The action spawned `claude -p` with `cwd` set to a per-case
`tempfile.mkdtemp(...)` working directory and no `--add-dir` flag, so
the subprocess could only read files inside that temp dir.

Skills that reference plugin-shipped reference files via the
documented `${CLAUDE_PLUGIN_ROOT}` plugin convention (e.g. shared
registries under `${CLAUDE_PLUGIN_ROOT}/data/*.yaml` or per-feature
config under `${CLAUDE_PLUGIN_ROOT}/spaces/*/*.md`) had every Read
and Grep denied because the resolved path was outside the allowed
working directory. The agent could never get past the first step
of any non-trivial skill that loads its own reference data.

Fix: resolve `PLUGIN_ROOT = SKILL_PATH.resolve().parent.parent`
(e.g. `plugins/<plugin>/skills/<skill>` -> `plugins/<plugin>`) at
module load and pass `--add-dir <PLUGIN_ROOT>` to the `claude -p`
subprocess.

`.resolve()` is required because `--add-dir` is interpreted relative
to the subprocess cwd (the per-case temp dir); a relative
`SKILL_PATH` (as set by the composite action input when callers pass
a workspace-relative path) would otherwise expand to a nonexistent
path inside that temp dir.
@nicknikolakakis
nicknikolakakis merged commit c94ec38 into main May 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant